﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Reflector.CodeModel;
using Reflector;
using Reflector.CodeModel.Memory;
using System.Threading;
using System.Diagnostics;

namespace SilverlightBrowserReflectorPlugin
{
    public partial class Viewer : UserControl
    {
        Uri url;
        List<string> jsFiles;
        List<string> xamlFiles;
        Dictionary<string, string> files = null;

        public Viewer()
        {
            InitializeComponent();
        }

        private void Translate()
        {
            try
            {
                BeginInvoke(new ThreadStart(delegate()
                {
                    this.toolStripProgressBar1.Value = 0;
                    this.toolStripStatusLabel1.Text = "Loading... " + this.url.ToString();
                }));

                /*
                SilverlightPackage.assemblyList = new List<IAssembly>();
                */

                Invoke(new ThreadStart(delegate()
                {
                    this.files = SilverlightPackage.Sniff(this.url, this.jsFiles, this.xamlFiles);
                }));

                if (this.files.Count != 0)
                {
                    BeginInvoke(new ThreadStart(delegate()
                    {
                        for (int i = 1; 1 != this.tabControl1.TabPages.Count; i++)
                        {
                            this.tabControl1.TabPages.RemoveAt(1);
                        }
                    }));
                }

                foreach (KeyValuePair<string, string> fileContent in this.files)
                {
                    BeginInvoke(new ThreadStart(delegate()
                    {
                        this.toolStripProgressBar1.Value = 25;
                        this.toolStripStatusLabel1.Text = "Sniffing JavaScript";
                    }));

                    TabPage page = new TabPage(fileContent.Key);

                    RichTextBox rtb = new RichTextBox();

                    rtb.Text = fileContent.Value;
                    rtb.Dock = DockStyle.Fill;

                    page.Controls.Add(rtb);

                    BeginInvoke(new ThreadStart(delegate()
                    {
                        this.tabControl1.TabPages.Add(page);
                    }));
                }

                /*
                if (SilverlightPackage.assemblyList != null)
                {

                    ILanguageManager langMan = SilverlightPackage.ServiceProvider.GetService(typeof(ILanguageManager)) as ILanguageManager;

                    StringFormatter format = new StringFormatter();

                    ILanguageWriter cs = langMan.ActiveLanguage.GetWriter(format, new Config());

                    ITranslatorManager manager = SilverlightPackage.ServiceProvider.GetService(typeof(ITranslatorManager)) as ITranslatorManager;

                    ITranslator translator = manager.CreateDisassembler(null, null);

                    foreach (IAssembly assembly in SilverlightPackage.assemblyList)
                    {
                        foreach (IModule mod in assembly.Modules)
                        {
                            foreach (ITypeDeclaration type in mod.Types)
                            {

                                BeginInvoke(new ThreadStart(delegate()
                                {
                                    int changeValue = 75 / mod.Types.Count;
                                    if (this.toolStripProgressBar1.Value + changeValue < 100)
                                        this.toolStripProgressBar1.Value += changeValue;

                                    this.toolStripStatusLabel1.Text = "Creating " + type.Name + langMan.ActiveLanguage.FileExtension;
                                }));

                                if (type.Namespace.Length == 0 || type.Name == "<Module>" || type.Name == "<PrivateImplementationDetails>")
                                    continue;

                                INamespace namespace2 = new Namespace();

                                ITypeDeclaration typeDecl = translator.TranslateTypeDeclaration(type, true, true);

                                namespace2.Types.Add(typeDecl);

                                namespace2.Name = typeDecl.Namespace;

                                cs.WriteNamespace(namespace2);

                                string fileName = type.Name + langMan.ActiveLanguage.FileExtension;
                                TabPage page = new TabPage(fileName);

                                RichTextBox rtb = new RichTextBox();

                                rtb.Text = format.Value;
                                format.Clear();
                                rtb.Dock = DockStyle.Fill;

                                page.Controls.Add(rtb);



                                BeginInvoke(new ThreadStart(delegate()
                                {
                                    this.tabControl1.TabPages.Add(page);
                                }));

                            }
                        }
                        SilverlightPackage.Message = "Silverlight .NET Page Loaded";
                    }
                }
                */

                BeginInvoke(new ThreadStart(delegate()
                {
                    this.toolStripProgressBar1.Value = 100;
                    toolStripStatusLabel1.Text = SilverlightPackage.Message;

                }));

            }
            catch (Exception ex)
            {

                BeginInvoke(new ThreadStart(delegate()
                {
                    toolStripStatusLabel1.Text = SilverlightPackage.Message;

                }));
            }
        }

        public TabControl Tabs
        {
            get
            { return this.tabControl1; }
            set { this.tabControl1 = value; }
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            try
            {
                Uri url = new Uri(this.navigationURL.Text);

                this.webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted);

                this.webBrowser.Navigate(url);
            }
            catch (Exception ex)
            {
                this.toolStripStatusLabel1.Text = "The URL entered is not a proper URI";
            }
        }

        void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            HtmlDocument doc = this.webBrowser.Document;
            this.url = doc.Url;
            this.xamlFiles = findXamlFiles(doc);
            this.jsFiles = findJsFiles(doc);

            Thread t = new Thread(Translate);
            t.Start();
        }

        static List<string> findXamlFiles(HtmlDocument doc)
        {
            List<string> xamlFiles = new List<string>();
            foreach (HtmlElement obj in doc.GetElementsByTagName("object"))
            {
                string type = obj.GetAttribute("type");
                if (type != "application/ag-plugin") continue;

                foreach (HtmlElement param in obj.GetElementsByTagName("param"))
                {
                    string name = param.GetAttribute("name");
                    if (name != "source") continue;

                    string value = param.GetAttribute("value");
                    if (string.IsNullOrEmpty(value)) continue;

                    xamlFiles.Add(value);
                    break;
                }
            }
            return xamlFiles;
        }

        static List<string> findJsFiles(HtmlDocument doc)
        {
            List<string> jsFiles = new List<string>();
            foreach (HtmlElement script in doc.GetElementsByTagName("script"))
            {
                string src = script.GetAttribute("src");
                if (string.IsNullOrEmpty(src)) continue;

                jsFiles.Add(src);
            }
            return jsFiles;
        }
    }
}
